<?php declare(strict_types=1);


namespace App\Util;


use Illuminate\Support\Facades\Schema;

class TimeUtil
{
    const ORDER_TABLE = "orders";
    const BILL_LOG_TABLE = "bill_logs";
    const BILL_TABLE = "bills";
    const START_DATE = "2024-10-01 00:00:00";

    public function getBillTableName(string $base_time): string
    {
        $billTableName = self::BILL_TABLE;
        $table = $billTableName . "_" . date("Y", strtotime($base_time));
        if (Schema::connection("bi")->hasTable($table)) {
            return $table;
        }
        return $billTableName;
    }

    public function getBillLogTableName(string $base_time): string
    {
        $billLogTableName = self::BILL_LOG_TABLE;//  //orders_20240813
        $table = $billLogTableName . "_" . date("Ym", strtotime($base_time));
        if (Schema::connection("bi")->hasTable($table)) {
            return $table;
        }
        return $billLogTableName;
    }


    public function getTable(array $times): array
    {
        foreach ($times as $k => $v) {
            $table = $this->getBillLogTableName($v[0]);
            $tmp[] = [
                "time" => $v,
                "table" => $table
            ];;
        }
        $data = [];
        //再次循环整理数据
        foreach ($tmp as $v) {
            $data[$v["table"]][] = $v["time"];
        }
        return $data;
    }

    //获取账单月表数据
    public function getTableBillLog(array $times): array
    {
        foreach ($times as $k => $v) {
            $table = $this->getBillLogTableName($v[0]);
            $tmp[] = [
                "time" => $v,
                "table" => $table
            ];
        }
        $data = [];
        //再次循环整理数据
        foreach ($tmp as $v) {
            $data[$v["table"]][] = $v["time"];
        }
        return $data;
    }


    public function queryToSql($query): string
    {
        $bindings = $query->getBindings();
        $sql = str_replace('?', '%s', $query->toSql());
        return sprintf($sql, ...$bindings);
    }

    //获取归档年份
    public function getTableBill(array $times): array
    {
        foreach ($times as $k => $v) {
            $table = $this->getBillTableName($v[0]);
            $tmp[] = [
                "time" => $v,
                "table" => $table
            ];
        }
        $data = [];
        //再次循环整理数据
        foreach ($tmp as $v) {
            $data[$v["table"]][] = $v["time"];
        }
        return $data;
    }

    public function getDayRange(array $times): array
    {
        list($start, $end) = $times;
        //2024-09-12
        $startDay = date("d", strtotime($start));
        $endDay = date("d", strtotime($end));
        $days = [];
        for ($d = $startDay; $d <= $endDay; $d++) {
            $d = (string)$d;
            $d = (strlen($d) == 1) ? "0" . $d : $d;
            $days[] = date("Y-" . "m" . "-" . $d, strtotime($start));
        }
        return $days;
    }

    //求day的最大值和最小值
    public function getYearDayRange(array $times): array
    {
        $min = "";
        $max = "";
        foreach ($times as $v) {
            list($start, $end) = $v;
            if (empty($min)) {
                $min = $start;
            }
            if (empty($max)) {
                $max = $end;
            }
            //比较交换数据
            if ($min > $start) {
                $min = $start;
            }

            if ($max < $end) {
                $max = $end;
            }
        }
        return [$min, $max];
    }

    public function getMonthRange(string $month)
    {
        $date_start = date('Y-m-01 00:00:00', strtotime($month));
        $date_end = date('Y-m-t 23:59:59', strtotime($month));
        return [$date_start,$date_end];
    }


    public function get(int $curHdIndex)
    {
        switch ($curHdIndex) {
            case 1://今日
                $date_start = date('Y-m-d 00:00:00');
                $date_end = date('Y-m-d 23:59:59');
                $curHdTit = '今日';
                break;
            case 2://昨日
                $date_start = date('Y-m-d 00:00:00', strtotime("-1 day"));
                $date_end = date('Y-m-d 23:59:59', strtotime("-1 day"));
                $curHdTit = '昨日';
                break;
            case 3://上周
                $date_start = date('Y-m-d 00:00:00', strtotime('last week'));
                $date_end = date('Y-m-d 23:59:59', strtotime('this week -1 day'));
                $curHdTit = '上周';
                break;
            case 4://本月
                $date_start = date('Y-m-01 00:00:00');
                $date_end = date('Y-m-t 23:59:59');
                $curHdTit = '本月';
                break;
            case 5://上月
                $date_start = date('Y-m-01 00:00:00', strtotime('first day of last month'));
                $date_end = date('Y-m-t 23:59:59', strtotime('last day of last month'));
                $curHdTit = '上月';
                break;
            default:
                throw new \Exception("curHdIndex参数异常");
        }
        return [
            ($date_start),
            ($date_end),
            $curHdTit
        ];
    }

    //分析时间 按照年来分析
    public function rangeTimeYear(string $startDate, string $endDate): array
    {
        //结束时间必须大于开始时间
        if (strtotime($endDate) <= strtotime($startDate)) {
            throw new \Exception("结束时间必须大于开始时间");
        }
        $ch = $this->chUseTime($startDate);
        if ($ch == false) {
            throw new \Exception("开始时间必须大于2024-09-13 00:00:00");
        }
        return $this->rangeTimeSameYearByYear($startDate, $endDate);
    }

    protected function rangeTimeSameYearByYear(string $startDate, string $endDate): array
    {
        $startYear = date("Y", strtotime($startDate));
        $endYear = date("Y", strtotime($endDate));
        $return = []; //[$start,$end]
        for ($y = $startYear; $y <= $endYear; $y++) {
            $y = (string)$y;
            $start = date($y . "-m" . "-d" . " 00:00:00", strtotime($startDate));
            $end = date($y . "-m" . "-d" . " 23:59:59", strtotime($endDate));
            if ($startYear != $endYear) {
                $startTmp = date($y . "-01" . "-01" . " 00:00:00", strtotime($start));
                $endTmp = date($y . "-12" . "-31" . " 23:59:59", strtotime($end));
                if ($y == $startYear) {
                    $end = $endTmp;
                } else if ($y == $endYear) {
                    $start = $startTmp;
                } else {
                    $start = $startTmp;
                    $end = $endTmp;
                }
            }
            $tmp = [($start), ($end)];
            $return[] = $tmp;
        }
        return $return;
    }


    //分析时间范围
    //不能超过62天
    public function rangeTimeMonth(string $startDate, string $endDate): array
    {
        $startDate = new \DateTime($startDate);
        $endDate = new \DateTime($endDate);

        $ch = $this->chUseTime($startDate->format("Y-m-d H:i:s"));
        if ($ch == false) {
            throw new \Exception("开始时间必须大于2024-10-01 00:00:00");
        }
        if (strtotime($endDate->format("Y-m-d H:i:s")) - strtotime($startDate->format("Y-m-d H:i:s")) > 62 * 3600 * 24) {
//            throw new \Exception("不能超过92天");
        }

//        $endDate->modify('+1 day'); // 包含结束日期的当天，所以需要+1天
        $ranges = [];

        $currentDate = clone $startDate; // 使用 clone 来避免修改原始对象

        while ($currentDate <= $endDate) {
            // 获取当前月份的第一天
            $firstDayOfMonth = clone $currentDate;
            $firstDayOfMonth->modify('first day of this month');

            // 获取当前月份可能的最后一天（考虑结束日期限制）
            $lastPossibleDay = clone $endDate;
            $lastDayOfMonth = clone $currentDate;
            $lastDayOfMonth->modify('last day of this month 23:59:59');
            // 如果当前月份的最后一天超出了给定的结束日期，则使用结束日期作为最后一天
            if ($lastDayOfMonth > $lastPossibleDay) {
                $lastDayOfMonth = $lastPossibleDay;
            }

            // 添加当前月份的范围到结果数组中
            $ranges[] = [
                $firstDayOfMonth->format('Y-m-d H:i:s'),
                $lastDayOfMonth->format('Y-m-d H:i:s')
            ];

            // 移动到下一个月
            $currentDate->modify('first day of next month');
        }

        return $ranges;
    }


    //检测不通过
    public function chUseTime(string $startDate): bool
    {
        if (strtotime($startDate) < strtotime(self::START_DATE)) {
            return false;
        }
        return true;
    }

}